package main;

import gui.DynamiclyConfGui;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import mutation.MutationManager;

//import com.sun.org.apache.xml.internal.serialize.OutputFormat;
/**
 * Main class where the program start from
 * 
 * @author Manassen
 * 
 */
public class HP {

	private static long startTime;

	/**
	 * 
	 * @param argv
	 *            get's two parameters 1) the config.ini path (you can always
	 *            use the one in the project out folder by run with
	 *            ..\out\config.ini as first arg 2)the seed file that will be
	 *            use for the random calculation <a
	 *            href="http://en.wikipedia.org/wiki/Random_seed">for more
	 *            information about seeding</a>
	 * 
	 */
	public static void main(String[] argv) {
		if (argv.length != 1)
			throw new RuntimeException("must get to parm config.ini path");
		startTime = new Date().getTime();
		loadConfGui(argv[0]);
		Configuration config = getConfiguration(argv);
		OutputFilesWriter outWriter = getOutWriter(config);
		MutationManager mutationManager = getMutationManager(config);
		GAinterface run = new GARun(outWriter, config, mutationManager);

		for (int i = 0; i < config.numberOfRepeats; i++) {
			run.initiate(i); // An independent run
			System.out.println("Starting Run " + i + " ...");
			run.execute();
			long runningTime = (new Date().getTime() - startTime) / 1000;
			System.out.println("Done. Time: " + runningTime
					+ " seconds. Faild " + mutationManager.numOfFailers
					+ " out of " + mutationManager.numOfIterations);
		}
		try {
			outWriter.close();
		} catch (IOException ex1) {
			throw new RuntimeException("Failed to close output file\n" + ex1);
		}
	}

	private static void loadConfGui(String filename) {
		Properties properties = new Properties();
		Lock lock = new ReentrantLock();
		Condition waitForGui = lock.newCondition();
		System.out.println("aa");
		try {
			properties.load(new FileInputStream(filename));
		} catch (IOException e) {
			e.printStackTrace();
		}
		/*
		 * MainView mv=new MainView(filename,waitForGui,lock,
		 * properties.getProperty("MutationRate"),
		 * properties.getProperty("CrossoverRate"),
		 * properties.getProperty("PopulationSize"),
		 * properties.getProperty("Generations"),
		 * properties.getProperty("RepeatTimes"),
		 * properties.getProperty("ReportEvery"),
		 * properties.getProperty("FitnessFunctionName"),
		 * Integer.parseInt(properties.getProperty("Dimensions")),
		 * properties.getProperty("MutationFileName"),
		 * properties.getProperty("PrefixOutputFiles"),
		 * properties.getProperty("Sequence")); mv.setVisible(true);
		 */
		// JScrollPane jsp=new JScrollPane();
		// jsp.add(new DynamiclyConfGui(filename, waitForGui, lock));
		DynamiclyConfGui dc = new DynamiclyConfGui(filename, waitForGui, lock);
		dc.setVisible(true);
		// jsp.setVisible(true);
		lock.lock();
		try {

			waitForGui.await();
			// mv.wait();
		} catch (InterruptedException e) {
			System.err.println("we were interputed");
		} finally {
			lock.unlock();
		}

	}

	/**
	 * extract the configuration from the argument given to the program
	 * 
	 * @param argv
	 *            a string array of length 1 for the config.ini path
	 * @return an object contains all the data from the configuration file
	 */
	private static Configuration getConfiguration(String[] argv) {
		if (argv.length != 1) {
			throw new RuntimeException(
					"Cannot run GA \n Usage: java main.GA <config file name> ");
		}
		Configuration config;
		System.out.print("Loading Configuration ...");
		String configFileName = argv[0];
		System.out.println("Configuration file name " + configFileName);
		// int seed;
		// try {
		// seed = parseInt(argv[1]);
		// } catch (NumberFormatException ex) { throw new
		// RuntimeException("Cannot parse "+argv[1]+" as a seed."); }

		try {
			config = new Configuration(configFileName);
		} catch (IOException ex1) {
			throw new RuntimeException(
					"Failed to find, open or read configuration file: "
							+ configFileName + "\n" + ex1);
		}

		System.out.println("OK!");
		return config;
	}

	/**
	 * 
	 * @param config
	 *            the config file of this run
	 * @return new output file writer from the config file
	 */
	private static OutputFilesWriter getOutWriter(Configuration config) {
		System.out.print("Creating output file writers ...");
		OutputFilesWriter outWriter;
		try {
			outWriter = new OutputFilesWriter(Long.toString(config.seed),
					config);
		} catch (IOException ex1) {
			throw new RuntimeException("Cannot open output file\n" + ex1);
		}
		System.out.println("OK!");
		return outWriter;
	}

	private static MutationManager getMutationManager(Configuration config) {
		System.out.print("Loading Mutation Manager ...");
		MutationManager mutationManager = new MutationManager(config);
		System.out.println("OK!");
		return mutationManager;
	}
}
